/**
 *
 */
package com.engine.Mangers;

import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import com.util.EngineUtil;
import com.wfe.db.SessionUtil;
import com.wfe.db.WorkFlowEngineQueryUtil;
import com.wfe.mapping.client.WfPlanTask;
import com.wfe.mapping.client.WfProject;
import com.wfe.mapping.client.WfProjectStatus;
import com.wfe.mapping.client.WfProjectTask;
import com.wfe.mapping.client.WfProjectTaskStatus;
import com.wfe.mapping.client.WfTaskRouting;
import com.wfe.mapping.client.WfTaskType;

/**
 * @author kareem_yehya
 * 
 */
public class StartRouting implements Runnable
{
	private static int fetchSize = 10;
	private static String fetchSizeParameter = "";

	// @Override
	public void run()
	{

		while(true)
		// for(int i = 0; i < 2; i++)
		{
			Session session = null;
			try
			{
				session = SessionUtil.getSession();
				// ------------------------- assigned process tasks
				System.out.println("Resume Start new Projects Routing main Thread");
				List<WfProjectTask> taskList = loadTasksNeedRoute(fetchSize, session);
				if(taskList.size() > 0)
				{

					for(WfProjectTask wfProjectTask : taskList)
					{
						// System.out.println(wfProjectTask.getRecid().longValue());

						// System.out.println(wfProjectTask.getWfProject().getRecid().longValue());
						WfProjectTask nextProjectTask = route(wfProjectTask, session);
						// --------Double check------------
						if(nextProjectTask.getWfProjectTaskStatus().getRecid().longValue() != 5)
						{
							updateTaskAfterRouting(wfProjectTask, session);
						}
						// ------------------

					}
				}

			}catch(Exception e)
			{
				e.printStackTrace();
			}finally
			{
				EngineUtil.closeSession(session);
			}
			// /----------------------
			try
			{
				Thread.sleep(1000);
			}catch(Exception e)
			{
				e.printStackTrace();
			}

		}

	}

	private WfProjectTask getWfProjectTaskById(long recid, Session session)
	{

		WfProjectTask wfProjectTask = null;

		try
		{

			wfProjectTask = getWfProjectTask(session, recid, 10).get(0);
			return wfProjectTask;

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getWfProjectTask(Session session, long TaskID, int maxResults)
	{

		Long task_ID = new Long(TaskID);
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(TaskID > 0)
		{
			criteria.add(Restrictions.eq("recid", task_ID));
		}
		if(maxResults > 0)
		{
			criteria.setMaxResults(maxResults);
		}
		return criteria.list();
	}

	/**
	 * set is routed true and set routing time
	 * 
	 * @param session
	 * 
	 * @param session
	 * 
	 * */
	private void updateTaskAfterRouting(WfProjectTask wfProjectTask, Session session)
	{

		try
		{

			// WfProjectTask pTask = getWfProjectTaskById(wfProjectTask.getRecid().longValue(), session);
			WfProjectTaskStatus sucessStatus = getWfProjectTaskStatusByID(1l, session); // success
			wfProjectTask.setWfProjectTaskStatus(sucessStatus);
			wfProjectTask.setIsRouted(true);
			wfProjectTask.setRouteTime(new Date());
			wfProjectTask.setIsProcessed(true);
			updateTask(wfProjectTask, session);
		}catch(Exception e)
		{
			e.printStackTrace();
		}

	}

	public WfTaskType getwfTaskTypeByTypeID(Long tasktype, Session session)
	{

		try
		{
			Criteria criteria = session.createCriteria(WfTaskType.class);
			criteria.add(Restrictions.eq("recid", tasktype));
			return (WfTaskType) criteria.list().get(0);

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	private WfProjectStatus getWfProjectStatusByID(long i, Session session)
	{

		WfProjectStatus wfProjectStatus = null;

		try
		{

			wfProjectStatus = WorkFlowEngineQueryUtil.getwfProjectStatusByID(i, session);
			return wfProjectStatus;

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	public static WfProjectTaskStatus getWfProjectTaskStatusByID(long i, Session session)
	{

		WfProjectTaskStatus wfProjectTaskStatus = null;
		try
		{

			Criteria criteria = session.createCriteria(WfProjectTaskStatus.class);
			criteria.add(Restrictions.eq("recid", new Long(i)));
			wfProjectTaskStatus = (WfProjectTaskStatus) criteria.list().get(0);
			return wfProjectTaskStatus;

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * get start created tasks only
	 * 
	 * @param session
	 * 
	 * @param session
	 * 
	 * */

	private List<WfProjectTask> loadTasksNeedRoute(int maxresults, Session session)
	{

		List<WfProjectTask> tasklist = null;
		try
		{

			WfTaskType taskType = getwfTaskTypeByTypeID(new Long(1l), session); // start

			WfProjectTaskStatus createdStatus = getWfProjectTaskStatusByID(5l, session);// created

			WfProjectStatus projectStatus = getWfProjectStatusByID(2, session);// //
			// inprocess

			tasklist = loadTasksNeedRoute(maxresults, taskType, createdStatus, projectStatus, session);
			return tasklist;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	// -------- get assigned status to assign the routing nodes

	public static WfProjectTask route(WfProjectTask projectTask, Session session)
	{

		try
		{

			WfProjectTaskStatus status = getWfProjectTaskStatusByID(4l, session);
			// System.out.println("inside the router");

			// ----------- orginal projecttask
			// WfProjectTask mainTask = getWfProjectTaskByID(projectTask.getRecid(), session);// start task
			// WfProjectTask mainTask = projectTask;

			// --------------- project
			// WfProject mainProject = getWfProjectByRec_ID(projectTask.getWfProject().getRecid(), session);// project

			WfProject mainProject = projectTask.getWfProject();

			// ------ all project tasks
			List<WfProjectTask> allProjectTasks = getWfProjectTasksByProject(mainProject, session);// all project tasks

			// --------------- which tasks the main task routing to routing list
			List<WfTaskRouting> routinglist = getWfTaskRouting(10, projectTask.getWfPlanTask(), session);// routing list after start

			if(routinglist == null || routinglist.size() == 0)
			{
				System.out.println("No any Routing For The Task " + projectTask.getRecid());

				projectTask.setIsProcessed(false);
				WfProjectTaskStatus noRoutingStatus = getWfProjectTaskStatusByID(8l, session);
				projectTask.setWfProjectTaskStatus(noRoutingStatus);
				updateTask(projectTask, session);
				return null;
			}// if end

			for(WfTaskRouting routeTask : routinglist)// start routing to list
			{
				for(WfProjectTask task : allProjectTasks)// all project tasks
				{

					// if(routeTask.getWfPlanTask2().getRecid() == task.getWfPlanTask().getRecid())

					System.out.println("routeTask.getWfPlanTask2().getRecid().longValue() =" + routeTask.getWfPlanTask2().getRecid().longValue());
					System.out.println("task.getWfPlanTask().getRecid().longValue() =" + task.getWfPlanTask().getRecid().longValue());
					if(routeTask.getWfPlanTask2().getRecid().longValue() == task.getWfPlanTask().getRecid().longValue())
					{
						task.setWfProjectTaskStatus(status);
						updateTask(task, session);
						System.out.println("Task To Be Routed Recid = " + task.getRecid().longValue());
						System.out.println("Project Recid = " + task.getWfProject().getRecid().longValue());
						// -----------return task to check it-----------
						return task;
						// -------------------
					}
				}
			}// for end
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}
		return projectTask;

	}

	@SuppressWarnings("unchecked")
	private static List<WfProjectTask> getWfProjectTasksByProject(WfProject project, Session session)
	{

		List<WfProjectTask> wfProjectTaskList = null;
		try
		{

			Criteria criteria = session.createCriteria(WfProjectTask.class);
			criteria.add(Restrictions.eq("wfProject", project));
			wfProjectTaskList = criteria.list();
			System.out.println("wfProjectTaskList" + wfProjectTaskList.size());
			System.out.println("Project_ID = " + project.getRecid().longValue());
			return wfProjectTaskList;

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	// ******** for test

	public static void main(String args[])
	{
		try
		{
			System.out.println(args.length);
			if(args.length > 0)
			{
				fetchSizeParameter = args[0];
				if(fetchSizeParameter != null && !fetchSizeParameter.equals(""))
				{
					fetchSize = Integer.parseInt(fetchSizeParameter);
					System.out.println("fetchSize = " + fetchSize);
				}
			}

			(new Thread(new StartRouting())).start();
		}catch(Exception e)
		{
			e.printStackTrace();
		}

	}

	// ******** for test
	// @SuppressWarnings("deprecation")
	public WfProjectTask loadDummyTask(long taskID, Session session)
	{

		try
		{

			WfProjectTask projectTask = WorkFlowEngineQueryUtil.getWfProjectTaskByID(session, taskID);
			return projectTask;

		}

		catch(Exception e)
		{
			System.out.println("Couldn't Load Expected Dummy Task");
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * created start tasks for inprocess projects only which updated by project init
	 * */

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> loadTasksNeedRoute(int maxresults, WfTaskType taskType, WfProjectTaskStatus createdStatus, WfProjectStatus projectStatus, Session session)
	{

		List<WfProjectTask> wfProjectTaskList = null;
		try
		{

			Criteria criteria = session.createCriteria(WfProjectTask.class);

			// ------------------------------------------------------ for test only
			// criteria.add(Restrictions.eq("recid", 126460166050365864l));
			// ------------------------------------------------------ for test only

			if(maxresults > 0)
			{
				criteria.setMaxResults(maxresults);
			}
			// /************** created tasks
			criteria.add(Restrictions.eq("wfTaskType", taskType));
			criteria.add(Restrictions.eq("wfProjectTaskStatus", createdStatus));// get
			// start
			// created
			// tasks
			criteria.add(Restrictions.isNull("isRouted"));// /??????
			criteria.add(Restrictions.isNull("routeTime"));

			Criteria criteria1 = criteria.createCriteria("wfProject");
			criteria1.add(Restrictions.eq("wfProjectStatus", projectStatus));

			wfProjectTaskList = criteria1.list();
			return wfProjectTaskList;

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	public static WfProject getWfProjectByRec_ID(Long recid, Session session)
	{
		Criteria criteria = session.createCriteria(WfProject.class);
		criteria.add(Restrictions.eq("recid", recid));
		return (WfProject) criteria.list().get(0);
	}

	@SuppressWarnings("unused")
	private static WfProjectTask getWfProjectTaskByID(Long taskID, Session session)
	{

		WfProjectTask wfProjectTask = null;
		try
		{

			wfProjectTask = WorkFlowEngineQueryUtil.getWfProjectTaskByID(session, taskID);
			return wfProjectTask;

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	@SuppressWarnings("unchecked")
	private static List<WfTaskRouting> getWfTaskRouting(int maxResults, WfPlanTask plantask, Session session)
	{

		List<WfTaskRouting> routingList = null;
		try
		{

			Criteria criteria = session.createCriteria(WfTaskRouting.class);
			criteria.add(Restrictions.eq("wfPlanTask1", plantask));
			routingList = criteria.list();
			return routingList;

		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	private static void updateTask(WfProjectTask task, Session session)
	{

		try
		{

			session.update(task);
			session.beginTransaction().commit();

		}catch(Exception e)
		{
			e.printStackTrace();
		}

	}

}
